#pragma once

#include <istdplug.h>
#include <maths.h>

class node_animation_track
{
public:
	enum animation_t
	{
		TRANSLATION,
		ROTATION,
		SCALE
	};

	enum axis_t
	{
		XAXIS,
		YAXIS,
		ZAXIS
	};

	node_animation_track();
	~node_animation_track();

	size_t add_key(size_t time, const matrix4 &tm);

	void set_key_values(int anim, int axis, const std::vector<ILinFloatKey> &val);
	void set_key_values(int anim, int axis, const std::vector<IBezFloatKey> &val);
	void set_key_values(int anim, int axis, const std::vector<ITCBFloatKey> &val);

	void set_key_values(const std::vector<ILinPoint3Key> &val);
	void set_key_values(const std::vector<IBezPoint3Key> &val);
	void set_key_values(const std::vector<ITCBPoint3Key> &val);

	void set_key_values(const std::vector<ILinRotKey> &val);
	void set_key_values(const std::vector<IBezQuatKey> &val);
	void set_key_values(const std::vector<ITCBRotKey> &val);

	void set_key_values(const std::vector<ILinScaleKey> &val);
	void set_key_values(const std::vector<IBezScaleKey> &val);
	void set_key_values(const std::vector<ITCBScaleKey> &val);

	void apply_initial_transforms(const matrix4 &tm);

	void clear();

	size_t get_num_keys() const;
	size_t get_length() const;

	vector3 get_key_translation(size_t key) const;
	vector3 get_key_rotation(size_t key) const;
	vector3 get_key_scale(size_t key) const;
	size_t get_key_time(size_t key) const;

private:
	class keyframe
	{
	public:
		keyframe();
		keyframe(const vector3 &translation, const vector3 &rotation, const vector3 &scale, size_t time);

		vector3 translation;
		vector3 rotation;
		vector3 scale;

		matrix4	tm;

		size_t	time;
	};

	typedef std::vector<keyframe>	keyframe_vec;

	keyframe_vec	m_keys;

	size_t			m_length;

	vector3			m_initial_pos;
	vector3			m_initial_rot;
	vector3			m_initial_scale;
};

class vertex_animation_track
{
public:
	vertex_animation_track();
	~vertex_animation_track();

	void clear();

	void add_key();
	void add_key(size_t time, mesh_ptr pose);

	void set_time(size_t key, size_t time);
	void set_pose(size_t key, mesh_ptr pose);

	size_t get_key_count() const;
	size_t get_length() const;

	size_t get_time(size_t key) const;
	mesh_ptr get_pose(size_t key) const;

private:
	class keyframe
	{
	public:
		keyframe();
		keyframe(size_t time, mesh_ptr pose);

		mesh_ptr	pose;
		size_t		time;
	};

	typedef std::vector<keyframe>	keyframe_vec;

	keyframe_vec	m_keys;

	size_t			m_length;
};

class animation
{
public:
	animation();
	~animation();

	void clear();

	void set_name(const std::string &name);

	void add_node_animation_track(const node_animation_track &track);
	void add_vertex_animation_track(const vertex_animation_track &track);

	bool has_node_animation_track() const;
	bool has_vertex_animation_track() const;

	std::string get_name() const;
	size_t get_length() const;

	size_t get_num_node_animations() const;
	size_t get_num_vertex_animations() const;

	node_animation_track get_node_animation_track(size_t id) const;
	vertex_animation_track get_vertex_animation_track(size_t id) const;

private:
	typedef std::vector<node_animation_track> node_track_vec;
	typedef std::vector<vertex_animation_track> vertex_track_vec;

	std::string			m_name;

	node_track_vec		m_node_tracks;
	vertex_track_vec	m_vertex_tracks;
};